<template>
  <a-modal
    class="image-cropper"
    v-model:visible="visible"
    title="编辑图片"
    :footer="false"
    @cancel="closeModal"
  >
    <vue-cropper
      ref="cropperRef"
      :img="imageUrl"
      :autoCrop="true"
      :fixedBox="false"
      :centerBox="true"
      :canMoveBox="true"
      :info="true"
      outputType="png"
    />
    <div style="margin-bottom: 16px" />
    <!-- 图片操作 -->
    <div class="image-cropper-actions">
      <a-space>
        <a-button @click="changeScale(1)" class="btn" :disabled="!canEdit">放大</a-button>
        <a-button @click="changeScale(-1)" class="btn" :disabled="!canEdit">缩小</a-button>
        <a-button @click="rotateLeft" class="btn" :disabled="!canEdit">左转</a-button>
        <a-button @click="rotateRight" class="btn" :disabled="!canEdit">右转</a-button>
      </a-space>
    </div>
    <!-- 协同编辑操作 -->
    <div class="image-edit-actions">
      <a-space>
        <a-button v-if="editingUser" disabled> {{ editingUser.userName }}正在编辑</a-button>
        <a-button v-if="canEnterEdit" type="primary" ghost @click="enterEdit">进入编辑</a-button>
        <a-button v-if="canExitEdit" danger ghost @click="exitEdit">退出编辑</a-button>
        <a-button type="primary" :loading="loading" :disabled="!canEdit" @click="handleConfirm" >确认</a-button>
      </a-space>
    </div>
  </a-modal>
</template>

<script lang="ts" setup>
import {computed, onUnmounted, ref, watchEffect} from 'vue'
import {uploadPictureUsingPost} from "@/api/pictureController";
import {message} from "ant-design-vue";
import {useLoginUserStore} from "@/stores/useLoginUserStore";
import PictureEditWebSocket from "@/utils";
import {PICTURE_EDIT_ACTION_ENUM, PICTURE_EDIT_MESSAGE_TYPE_ENUM} from "@/constants/picture";
import {SPACE_TYPE_ENUM} from "@/constants/space";

interface Props {
  imageUrl?: string
  picture?: API.PictureVO
  spaceId?: number
  space?: API.SpaceVO
  onSuccess?: (newPicture: API.PictureVO) => void
}
// 图片上传后至后端的请求逻辑
const loading = ref<boolean>(false);
const props = defineProps<Props>()

// 编辑器组件的引用
const cropperRef = ref()

// 向左旋转
const rotateLeft = () => {
  cropperRef.value.rotateLeft()
  // 发送websocket通知
  editAction(PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT)
}
// 向右旋转
const rotateRight = () => {
  cropperRef.value.rotateRight()
  // 发送websocket通知
  editAction(PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT)
}
// 缩放
const changeScale = (num: number) => {
  cropperRef.value.changeScale(num)
  // 发送websocket通知
  if (num > 0) {
    editAction(PICTURE_EDIT_ACTION_ENUM.ZOOM_IN)
  } else {
    editAction(PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT)
  }
}

/** 确认裁剪 */
const handleConfirm = () => {
  cropperRef.value.getCropBlob((blob: Blob) => {
    // blob 为已裁切的文件
    // 拼接图片url，任何都为png
    const fileName = ((props.picture?.name) || 'image') + '.png';
    const file = new File([blob], fileName, {type: blob.type});
    // 上传图片
    handleUpload({ file })
  })
}

/**
 * 上传图片到后端
 * @param file
 */
const handleUpload = async ({ file }: any) => {
  loading.value = true;
  try {

    // 得到图片的id，否则空;如果已经有该图片id，则为更新图片操作
    const params: API.PictureUploadRequest = props.picture ? {id: props.picture.id} : {};
    // 获取空间id
    params.spaceId = props.spaceId;
    // 等待前端有数据后调用后端接口
    const res = await uploadPictureUsingPost(params, {}, file);
    // 如果数据存在将图片信息传递给父组件
    if(res.data.code === 0 && res.data.data) {
      message.success('图片上传成功');
      props.onSuccess?.(res.data.data);
      closeModal();
    } else {
      message.error('图片上传失败，' + res.data.message);
    }
  } catch (error) {
    message.error('图片上传失败');
  } finally {
    //执行完毕后将loading值设置回来
    loading.value = false;
  }
};

/**
 * 控制弹窗是否可见,默认关闭
 */
const visible = ref(false)

// 打开弹窗
const openModal = () => {
  visible.value = true
}

// 暴露openModal函数，外部可以使用
defineExpose({
  openModal,
})

/**
 * 协同编辑
 */
// 获取当前用户
const loginUserStore = useLoginUserStore();
const loginUser = loginUserStore.loginUser;
// 正在编辑的用户
const editingUser = ref<API.UserVO>();
// 没有用户正在编辑中，可进入编辑
const canEnterEdit = computed(() => {
  return !editingUser.value;
})
// 正在编辑的用户是本人，可以退出编辑
const canExitEdit = computed(() => {
  return editingUser.value?.id === loginUser.id
})

// 可以编辑
const canEdit = computed(() => {
  // 不是团队空间，默认可编辑
  if(!isTeamSpace.value) {
    return true;
  }
  return editingUser.value?.id === loginUser.id
})
/**
 * 初始化websocket，绑定事件
 */
let websocket: PictureEditWebSocket | null

// 初始化 WebSocket 连接，绑定事件
const initWebsocket = () => {
  const pictureId = props.picture?.id
  if (!pictureId || !visible.value) {
    return
  }
  // 防止之前的连接未释放
  if (websocket) {
    websocket.disconnect()
  }
  // 创建 WebSocket 实例
  websocket = new PictureEditWebSocket(pictureId)
  // 建立 WebSocket 连接
  websocket.connect()

  // 监听通知消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.INFO, (msg) => {
    console.log('收到通知消息：', msg)
    message.info(msg.message)
  })

  // 监听错误消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ERROR, (msg) => {
    console.log('收到错误消息：', msg)
    message.error(msg.message)
  })

  // 监听进入编辑状态消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT, (msg) => {
    console.log('收到进入编辑状态消息：', msg)
    message.info(msg.message)
    editingUser.value = msg.user
  })

  // 监听编辑操作消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION, (msg) => {
    console.log('收到编辑操作消息：', msg)
    message.info(msg.message)
    switch (msg.editAction) {
      case PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT:
        cropperRef.value.rotateLeft()
        break
      case PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT:
        cropperRef.value.rotateRight()
        break
      case PICTURE_EDIT_ACTION_ENUM.ZOOM_IN:
        cropperRef.value.changeScale(1)
        break
      case PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT:
        cropperRef.value.changeScale(-1)
        break
    }
  })

  // 监听退出编辑状态消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT, (msg) => {
    console.log('收到退出编辑状态消息：', msg)
    message.info(msg.message)
    editingUser.value = undefined
  })
}

// 关闭弹窗
const closeModal = () => {
  visible.value = false
  // 断开连接
  if (websocket) {
    websocket.disconnect()
  }
  editingUser.value = undefined
}
/**
 * 编辑发送 WebSocket 消息的函数
 */
// 进入编辑状态
const enterEdit = () => {
  if (websocket) {
    // 发送进入编辑状态的消息
    websocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT,
    })
  }
}

// 退出编辑状态
const exitEdit = () => {
  if (websocket) {
    // 发送退出编辑状态的消息
    websocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT,
    })
  }
}

// 编辑图片操作
const editAction = (action: string) => {
  if (websocket) {
    // 发送编辑操作的请求
    websocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION,
      editAction: action,
    })
  }
}

/**
 * 判断是否为团队空间，只有团队空间才能协作
 */
const isTeamSpace = computed(() => {
  return props.space?.spaceType === SPACE_TYPE_ENUM.TEAM;
})

watchEffect(() => {
  //只有团队空间才初始化
  if(isTeamSpace.value) {
    initWebsocket()
  }
})

onUnmounted(() => {
  // 断开连接
  if (websocket) {
    websocket.disconnect()
  }
  editingUser.value = undefined
})

</script>

<style scoped>
.image-cropper-actions {
  text-align: center;
}
.image-edit-actions {
    text-align: center;
    margin-top: 10px;
}
.image-cropper .vue-cropper {
  height: 400px !important;
}
</style>
